// ------------------------------------------------------------------------------------------
// Licensed by Interprise Solutions.
// http://www.InterpriseSolutions.com
// For details on this license please visit  the product homepage at the URL above.
// THE ABOVE NOTICE MUST REMAIN INTACT.
// ------------------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Web;
using System.Xml;
using System.Threading;
using System.Globalization;
using InterpriseSuiteEcommerceCommon.InterpriseIntegration.JSONLib;
using System.Collections.Specialized;
using InterpriseSuiteEcommerceCommon.DTO;
using System.Text.RegularExpressions;
using InterpriseSuiteEcommerceCommon.Extensions;
namespace InterpriseSuiteEcommerceCommon
{
    [FlagsAttribute]
    public enum AddressTypes : int
    {
        Unknown = 0,
        Billing = 1,
        Shipping = 2,
        Shared = 3, //Used for same billing and shipping address e.g. AllowShipToDifferentThanBillTo
    }

    public enum ResidenceTypes : int
    {
        Unknown = 0,
        Residential = 1,
        Commercial = 2
    }


    /// <summary>
    /// Summary description for Address.
    /// </summary>
    [Serializable]
    public class Address
    {
        #region Variable Declarations

        private Customer _thisCustomer;
        private int m_SkinID = 1; // caller must set this if required to be non "1"
        private String m_LocaleSetting = Thread.CurrentThread.CurrentUICulture.Name;
        private String m_CustomerCode = String.Empty;
        private String m_AddressID = String.Empty;
        private int m_DisplayOrder = 0;
        private String m_Separator; // used for Display and ToString() line separators
        private AddressTypes m_AddressType = AddressTypes.Unknown;
        private ResidenceTypes m_ResidenceType = ResidenceTypes.Unknown;
        private String m_Name = String.Empty;
        private String m_NickName = String.Empty;
        private String m_FirstName = String.Empty;
        private String m_LastName = String.Empty;
        private String m_Company = String.Empty;
        private String m_Address1 = String.Empty;
        private String m_Suite = String.Empty;
        private String m_City = String.Empty;
        private String m_State = String.Empty;
        private String _postalCode = String.Empty;
        private String m_Country = String.Empty;
        private string _countryISOCode = String.Empty;
        private bool _isWithState = false;
        private String m_Phone = String.Empty;
        private String m_County = String.Empty;
        private String m_EMail = String.Empty;
        private String m_ISResidenceType = String.Empty;
        private String m_PaymentMethod = String.Empty;
        private String m_CardType = String.Empty;
        private String m_CardNumber = String.Empty;
        private String m_CardName = String.Empty;
        private String m_CardNameSalt = String.Empty;
        private String m_CardNameIV = String.Empty;
        private String m_CardExpirationMonth = String.Empty;
        private String m_CardExpirationYear = String.Empty;
        private string _cardStartMonth = String.Empty;
        private string _cardStartYear = String.Empty;
        private string _cardIssueNumber = String.Empty;
        private string _cardNumberMasked = String.Empty;
        private string _paymentMethodLastUsed = String.Empty;
        private string _shippingMethod;
        private string _shippingMethodGroup;
        private string _cardDescription = String.Empty;
        private string _paymentTermGroup;
        private string _plus4 = String.Empty;

        #endregion

        public Address()
        {
        }

        public static Address New(Customer forCustomer, AddressTypes withType)
        {
            return new Address(forCustomer, withType);
        }

        public static Address Get(Customer byCustomer, AddressTypes withType, string withID, Guid? giftRegistryID = null)
        {
            var thisAddress = new Address(byCustomer, withType);
            thisAddress.AddressID = withID;
            thisAddress.AddressType = withType;
            thisAddress.LoadByCustomer(byCustomer, withType, withID, giftRegistryID);

            return thisAddress;
        }

        private Address(Customer thisCustomer, AddressTypes addressType)
        {
            _thisCustomer = thisCustomer;
            ContactCode = thisCustomer.ContactCode;
            m_CustomerCode = thisCustomer.CustomerCode;
            m_AddressType = addressType;
        }
       
        public AddressDTO ForTransfer()
        {
            AddressDTO dto = new AddressDTO();
            dto.id = this.AddressID;
            dto.accountName = this.Name;
            dto.firstName = this.FirstName;
            dto.lastName = this.LastName;
            dto.address = this.Address1;
            dto.city = this.City;
            dto.state = this.State;
            dto.postalCode = this.PostalCode;
            dto.country = this.Country;
            dto.withState = this.IsWithState;
            dto.phone = this.Phone;
            dto.county = this.County;
            dto.email = this.EMail;
            dto.residenceType = this.ResidenceType;
            dto.cardType = this.CardType;
            dto.nameOnCard = this.CardName;
            dto.cardExpMonth = this.CardExpirationMonth;
            dto.cardExpYear = this.CardExpirationYear;
            dto.full = this.Full;
            dto.cardNumber = this.CardNumberMaskSafeDisplayFormat;

            return dto;
        }

        public static Address FromForm(Customer owningCustomer, AddressTypes type, NameValueCollection form)
        {
            Address preferredAddress = new Address(owningCustomer, type);

            if (null != form["FirstName"])
            {
                preferredAddress.FirstName = form["FirstName"];
            }
            if (null != form["LastName"])
            {
                preferredAddress.LastName = form["LastName"];
            }

            preferredAddress.Name = string.Format("{0} {1}", preferredAddress.FirstName, preferredAddress.LastName);

            if (null != form["Address"])
            {
                preferredAddress.Address1 = form["Address"];
            }
            if (null != form["Country"])
            {
                preferredAddress.Country = form["Country"];
            }
            if (null != form["ResidenceType"])
            {
                preferredAddress.ResidenceType = InterpriseHelper.ResolveResidenceType(form["ResidenceType"]);
            }
            if (null != form["City"])
            {
                preferredAddress.City = form["City"];
            }
            if (null != form["State"])
            {
                preferredAddress.State = form["State"];
            }
            if (null != form["PostalCode"])
            {
                preferredAddress.PostalCode = form["PostalCode"];
            }
            if (null != form["County"])
            {
                preferredAddress.County = form["County"];
            }
            if (null != form["Phone"])
            {
                preferredAddress.Phone = form["Phone"];
            }

            return preferredAddress;
        }

        public String ISResidenceType
        {
            get
            {
                return m_ISResidenceType;
            }
            set
            {
                m_ISResidenceType = value;
            }
        }

        public int SkinID
        {
            get
            {
                return m_SkinID;
            }
            set
            {
                m_SkinID = value;
            }
        }

        public String LocaleSetting
        {
            get
            {
                return m_LocaleSetting;
            }
            set
            {
                m_LocaleSetting = value;
            }
        }

        public String Separator
        {
            get
            {
                return (m_Separator == null ? "<br/>" : m_Separator);
            }
            set
            {
                m_Separator = value;
            }
        }

        /// <summary>
        /// The CustomerID associated with this address
        /// </summary>
        public String CustomerCode
        {
            get
            {
                return m_CustomerCode;
            }
            set
            {
                m_CustomerCode = value;
            }
        }

        /// <summary>
        /// The AddressID associated with this address
        /// </summary>
        [JSONSerializable("id")]
        public String AddressID
        {
            get
            {
                return m_AddressID;
            }
            set
            {
                m_AddressID = value;
            }
        }

        /// <summary>
        /// The Display order for this address
        /// </summary>
        public int DisplayOrder
        {
            get
            {
                return m_DisplayOrder;
            }
            set
            {
                m_DisplayOrder = value;
            }
        }

        [JSONSerializable("accountName")]
        public String Name
        {
            get
            {
                return m_Name;
            }
            set
            {
                m_Name = value.Trim();
            }
        }

        /// <summary>
        /// The Nick Name for this address
        /// </summary>
        public String NickName
        {
            get
            {
                return m_NickName;
            }
            set
            {
                m_NickName = value.Trim();
            }
        }

        /// <summary>
        /// The First Name for this address
        /// </summary>
        [JSONSerializable("firstName")]
        public String FirstName
        {
            get
            {
                return m_FirstName;
            }
            set
            {
                m_FirstName = value.Trim();
            }
        }

        /// <summary>
        /// The Last Name for this address
        /// </summary>
        [JSONSerializable("lastName")]
        public String LastName
        {
            get
            {
                return m_LastName;
            }
            set
            {
                m_LastName = value.Trim();
            }
        }

        /// <summary>
        /// The Company name for this address
        /// </summary>
        public String Company
        {
            get
            {
                return m_Company;
            }
            set
            {
                m_Company = value.Trim();
            }
        }

        /// <summary>
        /// The First address line for this address
        /// </summary>
        [JSONSerializable("address")]
        public String Address1
        {
            get
            {
                return m_Address1;
            }
            set
            {
                m_Address1 = value.Trim();
            }
        }

        /// <summary>
        /// The suite line for this address
        /// </summary>
        public String Suite
        {
            get
            {
                return m_Suite;
            }
            set
            {
                m_Suite = value.Trim();
            }
        }

        /// <summary>
        /// The City for this address
        /// </summary>
        [JSONSerializable("city")]
        public String City
        {
            get
            {
                return m_City;
            }
            set
            {
                m_City = value.Trim();
            }
        }

        /// <summary>
        /// The State for this address
        /// </summary>
        [JSONSerializable("state")]
        public String State
        {
            get
            {
                return m_State;
            }
            set
            {
                m_State = value.Trim();
            }
        }

        /// <summary>
        /// The postal code for this address
        /// </summary>
        [JSONSerializable("postalCode")]
        public String PostalCode
        {
            get
            {
                return _postalCode;
            }
            set
            {
                _postalCode = value.Trim();
            }
        }

        /// <summary>
        /// The plus4 for this address
        /// </summary>
        [JSONSerializable("plus4")]
        public String Plus4
        {
            get
            {
                return _plus4;
            }
            set
            {
                _plus4 = value.Trim();
            }
        }

        /// <summary>
        /// The Country name for this address
        /// </summary>
        [JSONSerializable("country")]
        public String Country
        {
            get
            {
                return m_Country;
            }
            set
            {
                m_Country = value.Trim();
            }
        }

        [JSONSerializable("withState")]
        public bool IsWithState
        {
            get { return _isWithState; }
        }

        public string CountryISOCode
        {
            get { return _countryISOCode; }
            set { _countryISOCode = value; }
        }

        /// <summary>
        /// The Phone number for this address
        /// </summary>
        [JSONSerializable("phone")]
        public String Phone
        {
            get
            {
                return m_Phone;
            }
            set
            {
                m_Phone = value.Trim();
            }
        }

        [JSONSerializable("county")]
        public String County
        {
            get
            {
                return m_County;
            }
            set
            {
                m_County = value.Trim();
            }
        }

        /// <summary>
        /// The EMail for this address
        /// </summary>
        [JSONSerializable("email")]
        public String EMail
        {
            get
            {
                return m_EMail;
            }
            set
            {
                m_EMail = value.Trim();
            }
        }

        /// <summary>
        /// Returns the AddressType (Unknown, Billing, Shipping, Account)
        /// Records retrieved from the Address table are Unknown
        /// Records retrieved from the Customer table are of the type the were pulled from
        /// </summary>
        public AddressTypes AddressType
        {
            get
            {
                return (m_AddressType);
            }
            set
            {
                m_AddressType = value;
            }
        }

        /// <summary>
        /// Returns the ResidenceType (Unknown, Commercial, Residential, etc...)
        /// </summary>
        [JSONSerializable("residenceType")]
        public ResidenceTypes ResidenceType
        {
            get
            {
                return (m_ResidenceType);
            }
            set
            {
                m_ResidenceType = value;
            }
        }

        /// <summary>
        /// The payment method for this address.
        /// </summary>
        public String PaymentMethod
        {
            get
            {
                if (m_PaymentMethod.Length == 0)
                {
                    m_PaymentMethod = "Credit Card";
                }
                return m_PaymentMethod;
            }
            set
            {
                m_PaymentMethod = value.Trim();
            }
        }

        /// <summary>
        /// The payment term group for this address.
        /// </summary>
        public string PaymentTermGroup
        {
            get { return _paymentTermGroup; }
            set { _paymentTermGroup = value; }
        }

        /// <summary>
        /// The Card Type for this address.
        /// </summary>
        [JSONSerializable("cardType")]
        public String CardType
        {
            get
            {
                return m_CardType;
            }
            set
            {
                m_CardType = value.Trim();
            }
        }

        /// <summary>
        /// The Card Name for this address.
        /// </summary>
        [JSONSerializable("nameOnCard")]
        public String CardName
        {
            get
            {
                return m_CardName;
            }
            set
            {
                m_CardName = value.Trim();
            }
        }

        /// <summary>
        /// The Card Number for this address.
        /// </summary>
        public String CardNumber
        {
            get
            {
                return m_CardNumber;
            }
            set
            {
                m_CardNumber = value.Trim();
            }
        }

        public String CardNumberSalt
        {
            get
            {
                return m_CardNameSalt;
            }
            set
            {
                m_CardNameSalt = value;
            }
        }

        public String CardNumberIV
        {
            get
            {
                return m_CardNameIV;
            }
            set
            {
                m_CardNameIV = value;
            }
        }

        /// <summary>
        /// The Card Expiration Month for this address.
        /// </summary>
        [JSONSerializable("cardExpMonth")]
        public String CardExpirationMonth
        {
            get
            {
                return m_CardExpirationMonth;
            }
            set
            {
                m_CardExpirationMonth = value.Trim();
            }
        }

        /// <summary>
        /// The Card Expiration Month for this address.
        /// </summary>
        [JSONSerializable("cardExpYear")]
        public String CardExpirationYear
        {
            get
            {
                return m_CardExpirationYear;
            }
            set
            {
                m_CardExpirationYear = value.Trim();
            }
        }

        public string ShippingMethod
        {
            get { return _shippingMethod; }
            set { _shippingMethod = value; }
        }

        public string ShippingMethodGroup
        {
            get { return _shippingMethodGroup; }
            set { _shippingMethodGroup = value; }
        }

        [JSONSerializable("full")]
        public string Full
        {
            get
            {
                StringBuilder output = new StringBuilder();

                if (!CommonLogic.IsStringNullOrEmpty(this.Address1))
                {
                    output.Append(this.Address1);
                }

                if (!CommonLogic.IsStringNullOrEmpty(this.City))
                {
                    output.Append(", ");
                    output.Append(this.City);
                }

                if (!CommonLogic.IsStringNullOrEmpty(this.PostalCode))
                {
                    output.Append(", ");
                    output.Append(this.PostalCode);
                }

                if (!CommonLogic.IsStringNullOrEmpty(this.State))
                {
                    output.Append(", ");
                    output.Append(this.State);
                }

                if (!CommonLogic.IsStringNullOrEmpty(this.Country))
                {
                    output.Append(", ");
                    output.Append(this.Country);
                }

                string display = output.ToString();
                
                int displayLength = 100;
                // ensure length
                if (display.Length > displayLength)
                {
                    display = display.Substring(0, displayLength - 3);
                    display += "...";
                }

                return display;
            }
            set { }
        }


        /// <summary>
        /// The ECheck Account Number Code for this address.
        /// </summary>
        public String DisplayPaymentMethod(Customer ViewingCustomer)
        {
            String PMCleaned = AppLogic.CleanPaymentMethod(this.PaymentMethod);
            if (PMCleaned == AppLogic.ro_PMMicropay)
            {
                return String.Format(AppLogic.GetString("account.aspx.4", m_SkinID, m_LocaleSetting) + " - {0}", ViewingCustomer.FormatBasedOnMyCurrency(AppLogic.GetMicroPayBalance(this.CustomerCode)));
            }
            if (PMCleaned == AppLogic.ro_PMCreditCard)
            {
                return String.Format("{0} - {1}: {2} {3}/{4}", AppLogic.GetString("address.cs.11", m_SkinID, m_LocaleSetting), m_CardType, AppLogic.SafeDisplayCardNumber(this.CardNumber, string.Empty, 0), this.CardExpirationMonth, this.CardExpirationYear);
            }
            return String.Empty;
        }

        public void Clear()
        {
            m_CustomerCode = String.Empty;
            m_AddressID = String.Empty;
            m_DisplayOrder = 0;

            m_AddressType = AddressTypes.Unknown;
            m_ResidenceType = ResidenceTypes.Unknown;

            m_NickName = String.Empty;
            m_FirstName = String.Empty;
            m_LastName = String.Empty;
            m_Company = String.Empty;
            m_Address1 = String.Empty;
            m_Suite = String.Empty;
            m_City = String.Empty;
            m_State = String.Empty;
            _postalCode = String.Empty;
            _plus4 = String.Empty;
            m_Country = String.Empty;
            _countryISOCode = string.Empty;
            m_Phone = String.Empty;
            m_PaymentMethod = String.Empty;
            m_CardType = String.Empty;
            m_CardNumber = String.Empty;
            m_CardName = String.Empty;
            m_CardExpirationMonth = String.Empty;
            m_CardExpirationYear = String.Empty;
            m_EMail = String.Empty;
        }

        public Customer ThisCustomer
        {
            get { return _thisCustomer; }
            set { _thisCustomer = value; }
        }

        public void MakeDefault()
        {
            InterpriseHelper.MakeDefaultAddress(this.ContactCode, this.AddressID, this.AddressType);
        }

        public void Save()
        {
            int id = 0;
            if (ThisCustomer.IsNotRegistered && int.TryParse(ThisCustomer.CustomerCode, out id))
            {
                using (SqlConnection con = new SqlConnection(DB.GetDBConn()))
                {
                    using (SqlCommand cmd = new SqlCommand("EcommerceSaveAnonymousAddress", con))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;
                        SqlParameter paramCustomerID = new SqlParameter("@CustomerID", SqlDbType.Int);
                        SqlParameter paramEmail = new SqlParameter("@Email", SqlDbType.NVarChar, 100);
                        SqlParameter paramName = new SqlParameter("@Name", SqlDbType.NVarChar, 200);
                        SqlParameter paramAddress = new SqlParameter("@Address", SqlDbType.NVarChar, 200);
                        SqlParameter paramCity = new SqlParameter("@City", SqlDbType.NVarChar, 50);
                        SqlParameter paramState = new SqlParameter("@State", SqlDbType.NVarChar, 10);
                        SqlParameter paramPostalCode = new SqlParameter("@PostalCode", SqlDbType.NVarChar, 30);
                        SqlParameter paramCounty = new SqlParameter("@County", SqlDbType.NVarChar, 50);
                        SqlParameter paramCountry = new SqlParameter("@Country", SqlDbType.NVarChar, 100);
                        SqlParameter paramPhone = new SqlParameter("@Phone", SqlDbType.NVarChar, 100);
                        SqlParameter paramResidenceType = new SqlParameter("@ResidenceType", SqlDbType.Int);
                        SqlParameter paramCardType = new SqlParameter("@CardType", SqlDbType.NVarChar, 30);
                        SqlParameter paramCardName = new SqlParameter("@CardName", SqlDbType.NVarChar, 100);
                        SqlParameter paramCardExpYear = new SqlParameter("@CardExpYear", SqlDbType.NVarChar, 10);
                        SqlParameter paramCardExpMonth = new SqlParameter("@CardExpMonth", SqlDbType.NVarChar, 10);
                        SqlParameter paramCardStartMonth = new SqlParameter("@CardStartMonth", SqlDbType.NVarChar, 10);
                        SqlParameter paramCardStartYear = new SqlParameter("@CardStartYear", SqlDbType.NVarChar, 10);
                        SqlParameter paramCardIssueNumber = new SqlParameter("@CardIssueNumber", SqlDbType.NVarChar, 100);
                        SqlParameter paramCardMaskedNumber = new SqlParameter("@CardMaskedNumber", SqlDbType.NVarChar, 60);
                        SqlParameter paramAddressType = new SqlParameter("@AddressType", SqlDbType.Int);

                        cmd.Parameters.Add(paramCustomerID);
                        cmd.Parameters.Add(paramEmail);
                        cmd.Parameters.Add(paramName);
                        cmd.Parameters.Add(paramAddress);
                        cmd.Parameters.Add(paramCity);
                        cmd.Parameters.Add(paramState);
                        cmd.Parameters.Add(paramPostalCode);
                        cmd.Parameters.Add(paramCounty);
                        cmd.Parameters.Add(paramCountry);
                        cmd.Parameters.Add(paramPhone);
                        cmd.Parameters.Add(paramResidenceType);
                        cmd.Parameters.Add(paramCardType);
                        cmd.Parameters.Add(paramCardName);
                        cmd.Parameters.Add(paramCardExpYear);
                        cmd.Parameters.Add(paramCardExpMonth);
                        cmd.Parameters.Add(paramCardStartMonth);
                        cmd.Parameters.Add(paramCardStartYear);
                        cmd.Parameters.Add(paramCardIssueNumber);
                        cmd.Parameters.Add(paramCardMaskedNumber);
                        cmd.Parameters.Add(paramAddressType);

                        paramCustomerID.Value = id;
                        paramEmail.Value = this.EMail;
                        paramName.Value = this.Name;
                        paramAddress.Value = this.Address1;
                        paramCity.Value = this.City;
                        paramState.Value = this.State;
                        paramPostalCode.Value = this.PostalCode;
                        paramCounty.Value = this.County;
                        paramCountry.Value = this.Country;
                        paramPhone.Value = this.Phone;
                        paramResidenceType.Value = (int)this.ResidenceType;
                        

                        string cardNumberMasked = Interprise.Framework.Base.Shared.Common.MaskCardNumber(this.CardNumber);
                        byte[] salt = InterpriseHelper.GenerateSalt();
                        byte[] iv = InterpriseHelper.GenerateVector();
                        string cardNumberCypher = InterpriseHelper.Encryption(this.CardNumber, salt, iv);

                        string cadrIssueNumberCypher = string.Empty;
                        if (!CommonLogic.IsStringNullOrEmpty(this.CardIssueNumber))
                        {
                            cadrIssueNumberCypher = InterpriseHelper.Encryption(this.CardIssueNumber, salt, iv);
                        }                        

                        paramCardName.Value=  this.CardName;
                        paramCardType.Value = this.CardType;
                        paramCardMaskedNumber.Value = cardNumberMasked;
                        paramCardExpMonth.Value = this.CardExpirationMonth;
                        paramCardExpYear.Value = this.CardExpirationYear;
                        paramCardStartMonth.Value = this.CardStartMonth;
                        paramCardStartYear.Value = this.CardStartYear;
                        paramCardIssueNumber.Value = cadrIssueNumberCypher;
                        paramAddressType.Value = (int)this.AddressType;

                        con.Open();
                        this.m_AddressID = cmd.ExecuteScalar().ToString();
                    }
                }
            }
        }

        public void Reload()
        {
            this.LoadByCustomer(ThisCustomer, this.AddressType, this.AddressID);
        }

        private string MaskCardNumber(string cardNumber)
        {
            int index = cardNumber.Length - 4;
            string last = cardNumber.Substring(index, 4);
            StringBuilder mask = new StringBuilder();
            for (int ctr = 0; ctr <= index; ctr++)
            {
                mask.Append("X");
            }
            mask.Append(last);

            return mask.ToString();
        }

        /// <summary>
        /// Return a count of number of addresses associated with this customerID
        /// </summary>
        public int Count(String CustomerID)
        {
            return DB.GetSqlN(String.Format("select count(*) as N from Address with (NOLOCK) where CustomerID={0}", CustomerID.ToString()));
        }

        public void CopyToShoppingCartDB(int ShoppingCartID, AddressTypes aAddressType)
        {
            //An address could be both Type Shipping and Billing save both to Customer if so.
            string sql = String.Empty;
            if ((aAddressType & AddressTypes.Billing) != 0)
            {
                sql = "BillingAddressID={0}";
            }
            if ((aAddressType & AddressTypes.Shipping) != 0)
            {
                if (sql.Length != 0)
                {
                    sql += ",";
                }
                sql += "ShippingAddressID={0}";
            }
            sql = "update ShoppingCart set " + sql + " where ShoppingCartID={1}";
            sql = String.Format(sql, this.m_AddressID, ShoppingCartID);
            DB.ExecuteSQL(sql);
        }

        public string CardNumberMasked
        {
            get { return _cardNumberMasked; }
            set { _cardNumberMasked = value; }
        }

        public string CardStartMonth
        {
            get { return _cardStartMonth; }
            set { _cardStartMonth = value; }
        }

        public string CardStartYear
        {
            get { return _cardStartYear; }
            set { _cardStartYear = value; }
        }

        public string CardIssueNumber
        {
            get { return _cardIssueNumber; }
            set { _cardIssueNumber = value; }
        }

        public string CardDescription
        {
            get { return _cardDescription; }
            set { _cardDescription = value; }
        }

        public string PaymentMethodLastUsed
        {
            get { return _paymentMethodLastUsed; }
            set { _paymentMethodLastUsed = value; }
        }

        [JSONSerializable("cardNumber")]
        public string CardNumberMaskSafeDisplayFormat
        {
            // NOTE :
            //  Interprise Masking is by X, while InterpriseSuiteEcommerce uses *
            get
            {
                if (_cardNumberMasked.Length <= 8)
                {
                    return _cardNumberMasked.Replace('X', '*');
                }
                else
                {
                    string val;
                    val = _cardNumberMasked.Replace('X', ' ').Trim();
                    return val.PadLeft(val.Length + 4, '*');
                }
            }
        }

        public string CardStartDate
        {
            get 
            {
                if(!CommonLogic.IsStringNullOrEmpty(_cardStartMonth) && 
                    !CommonLogic.IsStringNullOrEmpty(_cardStartYear) && _cardStartYear.Length == 4)
                {
                    return  CommonLogic.IIF(_cardStartMonth.Length < 2, _cardStartMonth.PadLeft(2, '0'), _cardStartMonth) +
                            _cardStartYear.Substring(2, 2);
                }
                else
                {
                    return string.Empty;
                }
            }
        }

        private void LoadCustomerBillingAddress(string addressId, bool isAnonymous)
        {

            using (SqlConnection con = DB.NewSqlConnection())
            {
                con.Open();
                using (IDataReader reader = DB.GetRSFormat(con, "exec EcommerceGetAddress @CustomerCode = {0}, @AddressType = {1}, @AddressID = {2}, @IsAnonymous = {3}, @WebsiteCode = {4}, @ContactCode = {5}",
                    DB.SQuote(this.CustomerCode),
                    (int)AddressTypes.Billing,
                    CommonLogic.IIF(string.IsNullOrEmpty(addressId), "null", DB.SQuote(addressId)),
                    Convert.ToInt32(isAnonymous),
                    DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode),
                    DB.SQuote(ThisCustomer.ContactCode)))
                {
                    if (reader.Read())
                    {
                        // Registered Customer..
                        if (!isAnonymous)
                        {
                            this.m_AddressID = DB.RSField(reader, "CreditCardCode");
                            this.CustomerCode = DB.RSField(reader, "CustomerCode");
                            this.ContactCode = ThisCustomer.ContactCode;
                            this.m_Name = DB.RSField(reader, "CustomerName");
                            this.m_Address1 = DB.RSField(reader, "Address");
                            this.m_City = DB.RSField(reader, "City");
                            this.m_State = DB.RSField(reader, "State");
                            this._postalCode = DB.RSField(reader, "PostalCode");
                            this.m_Country = DB.RSField(reader, "Country");
                            this._countryISOCode = DB.RSField(reader, "CountryISOCode");
                            this._isWithState = DB.RSFieldBool(reader, "IsWithState");
                            this.m_County = DB.RSField(reader, "County");
                            this.m_Phone = DB.RSField(reader, "Telephone");
                            this.m_ResidenceType = InterpriseHelper.ResolveResidenceType(DB.RSField(reader, "ResidenceType"));
                            this.m_EMail = DB.RSField(reader, "Email");

                            // credit card information.....
                            this.m_CardName = DB.RSField(reader, "NameOnCard");
                            this.CardType = DB.RSField(reader, "CreditCardType");

                            this._cardNumberMasked = DB.RSField(reader, "MaskedCardNumber");

                            string expMonth = DB.RSField(reader, "ExpMonth");
                            if (!CommonLogic.IsStringNullOrEmpty(expMonth))
                            {
                                this.m_CardExpirationMonth = InterpriseHelper.FromInterpriseExpMonth(expMonth);
                            }
                            this.m_CardExpirationYear = DB.RSField(reader, "ExpYear");

                            string startMonth = DB.RSField(reader, "StartMonth");
                            if (!CommonLogic.IsStringNullOrEmpty(startMonth))
                            {
                                this._cardStartMonth = InterpriseHelper.FromInterpriseExpMonth(startMonth);
                            }
                            this._cardStartYear = DB.RSField(reader, "StartYear");

                            this._plus4 = CommonLogic.IIF(DB.RSFieldInt(reader, "Plus4") > 0, DB.RSFieldInt(reader, "Plus4").ToString("0000.##"), String.Empty);
                        }
                        else
                        {
                            // Anonymous Customer
                            this.m_AddressID = DB.RSFieldInt(reader, "Counter").ToString();
                            this.CustomerCode = DB.RSFieldInt(reader, "CustomerID").ToString();
                            this.m_Name = DB.RSField(reader, "Name");
                            this.m_Address1 = DB.RSField(reader, "Address");
                            this.m_City = DB.RSField(reader, "City");
                            this.m_State = DB.RSField(reader, "State");
                            this._postalCode = DB.RSField(reader, "PostalCode");
                            this.m_County = DB.RSField(reader, "County");
                            this.m_Country = DB.RSField(reader, "Country");
                            this._countryISOCode = DB.RSField(reader, "CountryISOCode");
                            this._isWithState = DB.RSFieldBool(reader, "IsWithState");
                            this.m_Phone = DB.RSField(reader, "Phone");
                            this.m_ResidenceType = InterpriseHelper.ResolveResidenceType(DB.RSField(reader, "ResidenceType"));
                            this.m_EMail = DB.RSField(reader, "Email");

                            this.m_CardName = DB.RSField(reader, "CardName");
                            this.m_CardType = DB.RSField(reader, "CardType");
                            this._cardNumberMasked = DB.RSField(reader, "CardMaskedNumber");
                            this.m_CardExpirationMonth = DB.RSField(reader, "CardExpMonth");
                            this.m_CardExpirationYear = DB.RSField(reader, "CardExpYear");
                            this._cardStartMonth = DB.RSField(reader, "CardStartMonth");
                            this._cardStartYear = DB.RSField(reader, "CardStartYear");
                        }
                    }
                }
            }
        }

        // added by Ronald C. Fortuna to check if the string can be converted to an integer type.
        // this regular expression checks for whole numbers up to 15 digits long
        private bool IsInteger(string parString)
        {
            if (Regex.IsMatch(parString, @"^\d{1,15}$"))
                return true;
            else
                return false;
        }

        private void LoadCustomerShippingAddress(string addressId, bool isAnonymous, Guid? giftRegistryId)
        {

            using (var con = DB.NewSqlConnection())
            {
                string query = string.Format("exec EcommerceGetAddress @CustomerCode = {0}, @AddressType = {1}, @AddressID = {2}, @IsAnonymous = {3}, @WebsiteCode = {4}, @ContactCode = {5}, @RegistryId={6}, @BusinessType = {7}", 
                                                DB.SQuote(this.CustomerCode),
                                                (int)AddressTypes.Shipping,
                                                CommonLogic.IIF(string.IsNullOrEmpty(addressId), "NULL", DB.SQuote(addressId)),
                                                Convert.ToInt32(isAnonymous),
                                                DB.SQuote(InterpriseHelper.ConfigInstance.WebSiteCode),
                                                DB.SQuote(ThisCustomer.ContactCode),
                                                (giftRegistryId.HasValue)? DB.SQuote(giftRegistryId.HasValue.ToString()) : "NULL",
                                                DB.SQuote(ThisCustomer.DefaultPrice));
                con.Open();
                using (var reader = DB.GetRS(query, con))
                {
                    if (reader.Read())
                    {
                        if (!isAnonymous)
                        {
                            this.m_AddressID = DB.RSField(reader, "ShipToCode");
                            this.CustomerCode = DB.RSField(reader, "CustomerCode");
                            this.ContactCode = ThisCustomer.ContactCode;
                            this.m_Name = DB.RSField(reader, "ShipToName");
                            this.m_Address1 = DB.RSField(reader, "Address");
                            this.m_City = DB.RSField(reader, "City");
                            this.m_State = DB.RSField(reader, "State");
                            this._postalCode = DB.RSField(reader, "PostalCode");
                            this.m_Country = DB.RSField(reader, "Country");
                            this._countryISOCode = DB.RSField(reader, "CountryISOCode");
                            this._isWithState = DB.RSFieldBool(reader, "IsWithState");
                            this.m_County = DB.RSField(reader, "County");
                            this.m_Phone = DB.RSField(reader, "Telephone");
                            this.m_ResidenceType = InterpriseHelper.ResolveResidenceType(DB.RSField(reader, "AddressType"));
                            this.m_EMail = DB.RSField(reader, "Email");
                            this._shippingMethod = DB.RSField(reader, "ShippingMethod");
                            this._shippingMethodGroup = DB.RSField(reader, "ShippingMethodGroup");

                            this._plus4 = CommonLogic.IIF(DB.RSFieldInt(reader, "Plus4") > 0, DB.RSFieldInt(reader, "Plus4").ToString("0000.##"), String.Empty);
                        }
                        else
                        {
                            this.m_AddressID = DB.RSFieldInt(reader, "Counter").ToString();
                            this.CustomerCode = DB.RSFieldInt(reader, "CustomerID").ToString();
                            this.m_Name = DB.RSField(reader, "Name");
                            this.m_Address1 = DB.RSField(reader, "Address");
                            this.m_City = DB.RSField(reader, "City");
                            this.m_State = DB.RSField(reader, "State");
                            this._postalCode = DB.RSField(reader, "PostalCode");
                            this.m_County = DB.RSField(reader, "County");
                            this.m_Country = DB.RSField(reader, "Country");
                            this._countryISOCode = DB.RSField(reader, "CountryISOCode");
                            this._isWithState = DB.RSFieldBool(reader, "IsWithState");
                            this.m_Phone = DB.RSField(reader, "Phone");
                            this.m_ResidenceType = InterpriseHelper.ResolveResidenceType(DB.RSField(reader, "ResidenceType"));
                            this.m_EMail = DB.RSField(reader, "Email");
                            this._shippingMethod = DB.RSField(reader, "ShippingMethod");
                            this._shippingMethodGroup = DB.RSField(reader, "ShippingMethodGroup");
                            this._paymentTermGroup = DB.RSField(reader, "PaymentTermGroup");
                        }
                    }
                }
            }
        }

        public void LoadByCustomer(Customer thisCustomer, AddressTypes addressType)
        {
            // load the default...
            LoadByCustomer(thisCustomer, addressType, string.Empty, null);
        }

        public void LoadByCustomer(Customer thisCustomer, AddressTypes addressType, string addressId, Guid? registryId = null)
        {
            _thisCustomer = thisCustomer;
            this.CustomerCode = thisCustomer.CustomerCode;
            this.AddressType = addressType;
            
            if (!string.IsNullOrEmpty(this.CustomerCode))
            {
                switch (addressType)
                {
                    case AddressTypes.Billing:
                        LoadCustomerBillingAddress(addressId, thisCustomer.IsNotRegistered);
                        break;
                    case AddressTypes.Shipping:
                        bool isAnonymous = thisCustomer.IsNotRegistered;

                        ////force the code to load the giftregistry billing addresss
                        if (registryId.HasValue) { isAnonymous = false; }
                        LoadCustomerShippingAddress(addressId, isAnonymous, registryId);
                        break;
                }
            }
            else
            {
                this.Clear();
            }
        }

        public static void Update(Customer thisCustomer, Address thisAddress)
        {
            switch (thisAddress.AddressType)
            {
                case AddressTypes.Billing:
                    InterpriseHelper.UpdateCustomerBillToInfo(thisCustomer, thisAddress);
                    break;
                case AddressTypes.Shipping:
                    InterpriseHelper.UpdateCustomerShipToInfo(thisCustomer, thisAddress);
                    break;
            }
        }

        public String DisplayHTML(bool Checkout)
        {
            return DisplayString(Checkout, true, true, "<br/>");
        }

        public override string ToString()
        {
            return DisplayString(false, false, true, "<br/>");
        }

        public string DisplayString(bool Checkout, bool IncludePhone, bool IncludeName, String Separator)
        {
            string s = String.Empty;
            string postal = PostalCode;

            if (!Plus4.IsNullOrEmptyTrimmed())
            {   
                postal = String.Format("{0}-{1}", PostalCode, Plus4);
            }
     

            StringBuilder tmpS = new StringBuilder(1000);
            if (IncludeName)
            {
                tmpS.Append(String.Format("{0} {1}", Name, Separator));
            }
            tmpS.Append(CommonLogic.IIF(this.m_Company.Length != 0, Company + Separator, ""));
            tmpS.Append(CommonLogic.IIF(this.m_Address1.Length != 0, Address1 + Separator, ""));
            tmpS.Append(CommonLogic.IIF(this.m_Suite.Length != 0, Suite + Separator, ""));
            s = CommonLogic.IIF(this.m_County.Length != 0, String.Format("{0}, {1}, {2} {3}", City, County, State, postal), String.Format("{0}, {1} {2}", City, State, postal));
            if (s.Length > 3) { tmpS.Append(s + Separator); }
            tmpS.Append(CommonLogic.IIF(this.m_Country.Length != 0, Country + Separator, ""));
            if (IncludePhone) { tmpS.Append(CommonLogic.IIF(this.m_Phone.Length != 0, Phone + Separator, "")); }
            return tmpS.ToString();
        }

        public string DisplayCardHTML()
        {
            return DisplayCardString("<br/>");
        }

        public string DisplayCardString(string separator)
        {
            StringBuilder tmpS = new StringBuilder(1000);
            tmpS.Append(this.CardName + separator);
            tmpS.Append(String.Format("{0}: {1}{2}", this.CardType, AppLogic.SafeDisplayCardNumber(CardNumber, string.Empty, 0), separator));
            tmpS.Append(String.Format("{0:0#}/{1:000#}{2}", this.CardExpirationMonth, this.CardExpirationYear, separator));
            return tmpS.ToString();
        }

        static public String StaticGetAddressSelectList(Customer ThisCustomer, bool RenamePrimary, String SelectName, bool AddPrimary, out int NumNonDefaultFound)
        {
            StringBuilder tmpS = new StringBuilder(4096);
            NumNonDefaultFound = 0;
            tmpS.Append("<select class=\"addressselect\" size=\"1\" name=\"" + SelectName + "\" id=\"" + SelectName + "\">\n");
            if (AddPrimary)
            {
                String s = String.Empty;
                if (ThisCustomer.PrimaryShippingAddressID != String.Empty)
                {
                    String nm = AppLogic.GetString("address.cs.10", ThisCustomer.SkinID, ThisCustomer.LocaleSetting);
                    tmpS.Append("<option value=\"" + ThisCustomer.PrimaryShippingAddressID.ToString() + "\">" + HttpContext.Current.Server.HtmlEncode(nm) + "</option>");
                }
            }
            String sql = "SELECT * FROM CustomerShipToView with (NOLOCK) WHERE CustomerCode=" + DB.SQuote(ThisCustomer.CustomerCode.ToString()) +
                         " AND ShipToCode <> " + DB.SQuote(ThisCustomer.PrimaryShippingAddressID.ToString());


            using (SqlConnection con = DB.NewSqlConnection())
            {
                con.Open();
                using (IDataReader rs = DB.GetRSFormat(con, sql))
                {
                    while (rs.Read())
                    {
                        String addrID = DB.RSField(rs, "ShipToCode");
                        NumNonDefaultFound++; // tick non-primary counter
                        String nm = String.Empty;
                        if (nm.Length == 0)
                        {
                            nm = DB.RSField(rs, "ShipToName");
                        }
                        tmpS.Append("<option value=\"" + addrID.ToString() + "\">" + HttpContext.Current.Server.HtmlEncode(nm) + "</option>");
                    }
                }
            }

            tmpS.Append("</select>\n");
            return tmpS.ToString();
        }

        public Guid? RegistryID { get; set; }

        public string RegistryTextSelection { get; set; }

        public string ContactCode { get; set; }
    }

    public class Addresses : ArrayList
    {
        public Addresses() { }

        public new Address this[int index]
        {
            get
            {
                return (Address)base[index];
            }
            set
            {
                base[index] = value;
            }
        }

        public void LoadCustomer(Customer thisCustomer, AddressTypes addressType)
        {
            switch (addressType)
            {
                case AddressTypes.Billing:

                    using (SqlConnection con = DB.NewSqlConnection())
                    {
                        con.Open();
                        using (IDataReader reader = DB.GetRSFormat(con, "SELECT CreditCardCode FROM CustomerCreditCard with (NOLOCK) WHERE CustomerCode = {0} AND IsActive = 1", DB.SQuote(thisCustomer.CustomerCode)))
                        {
                            while (reader.Read())
                            {
                                string addressId = DB.RSField(reader, "CreditCardCode");
                                Address thisAddress = new Address();
                                thisAddress.LoadByCustomer(thisCustomer, addressType, addressId);
                                this.Add(thisAddress);
                            }
                        }
                    }
                    break;
                case AddressTypes.Shipping:

                    using (SqlConnection con = DB.NewSqlConnection())
                    {
                        con.Open();
                        using (IDataReader rs = DB.GetRSFormat(con, "SELECT ShipToCode FROM CustomerShipToView with (NOLOCK) WHERE CustomerCode={0}", DB.SQuote(thisCustomer.CustomerCode)))
                        {
                            while (rs.Read())
                            {
                                String addressId = DB.RSField(rs, "ShipToCode");
                                Address newAddress = new Address();
                                newAddress.LoadByCustomer(thisCustomer, addressType, addressId);
                                this.Add(newAddress);
                            }
                        }
                    }
                    break;
            }
        }
    }

}






